package pro.control.core;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.*;
import javax.swing.JLayeredPane;
import pro.model.data.*;
import pro.view.adaptor.Wrapper;
import pro.view.core.Card;
import pro.view.core.GameView;
import pro.view.core.IHolder;

/**
 * @author  sangwo.y
 */
public class Driver implements MouseMotionListener, MouseListener {
	
	private static Driver selfInstance;
	private GameView gv;
	private Card currentCard;
	private List<IHolder> holders;
	private IHolder srcHolder;
	private IHolder dstHolder;
	private List<Card> cardsToDrag;
	private boolean dragging = false;
	private Wrapper model;
	
	public static Driver getInstanceOf(GameView gv, Wrapper model) {
		if (selfInstance==null) {
			selfInstance = new Driver(gv, model);
			return selfInstance;
		} else { 
			System.out.println("no new instance");
			selfInstance.setModel(model);
			return selfInstance; }
	}
	
	private Driver(GameView gv, Wrapper model) { //adapter too!
		this.gv=gv;		
		this.model=model;
		holders=model.getHolders();
		//setHolders();
	}
	
	/**
	 * @param model  the model to set
	 * @uml.property  name="model"
	 */
	public void setModel(Wrapper model) {
		this.model=model;
		holders=model.getHolders();
//		setHolders();
	}
	
//	private void setHolders() {
//		holders=gv.getHolders();
//	}
	
	
	private int getTopLayer() {
		int top = 0;
		for (IHolder ih: holders) {
			if (top<ih.size()) 
				top = ih.size();
		}
		return top;
	}
	
	public void resetGame() {
		System.out.println("gv.newGame()");
		gv.newGame();
	}
	
	
	public void mouseMoved(MouseEvent e) {
		currentCard = null;
		for (IHolder ih: holders) {
			List<Card> lc = ih.getCards();
				//if () {
					for (Card card: lc) {
						if (card.isMouseOver(e.getPoint())) {
							if (currentCard!=null) {
								int a = JLayeredPane.getLayer(card);					
								int b = JLayeredPane.getLayer(currentCard);
								if (a>b) currentCard=card;
							} else {currentCard=card; }
						}
					}
				//}
		}
	}

	
	public void mouseDragged(MouseEvent me) {
		if (currentCard!=null)	{ // && model accepts the move (some bool - ok)
			
			for (Card c: cardsToDrag) {
				c.setLocation(me.getX()-c.offsetX, me.getY()-c.offsetY);
			}
			
		}

	}
	
	
	public void mouseClicked(MouseEvent e) {
		
		
		
		if ((e.getClickCount()==2)	||	(e.getClickCount()==4)) {
			System.out.println(e.getClickCount());
			mousePressed(e);
			List<IHolder> endCells = model.getEndCells();
			for (IHolder ih: endCells) {
				dstHolder=ih;
				System.out.println("to dstHolder.id: "+dstHolder.getId());
				System.out.println("to dstHolder.class: "+dstHolder.getClass());
				if (model.moveTo(ih)) break;
				mousePressed(e);
				
			}
			
		e.consume();
//			autoDrag=true;
			
		}
	}
	
	public void mouseEntered(MouseEvent e) {}
	public void mouseExited(MouseEvent e) {}


	public void mousePressed(MouseEvent e) {		
		if (currentCard!=null) { 
			cardsToDrag = currentCard.cardsToDrag();
			int n = cardsToDrag.size();
//			System.out.println("move from: "+currentCard.getHolder()+" n "+n);
			if (model.moveFrom(currentCard.getHolder(), n)) { //  model says OK! (make move)
				int top = getTopLayer() + 1;			
				for (Card card: cardsToDrag) {
					((JLayeredPane)gv.getContentPane()).setLayer(card, new Integer(top));
					//card.setText(top);
					card.setOffset(e.getPoint());
					top++;
				}
				srcHolder=currentCard.getHolder();
				dragging=true;
			} else {currentCard=null; }
		}
	}


	public void mouseReleased(MouseEvent e) {
		
//		if (autoDrag) {
//			System.out.println("hehe");
//			return;
//		}
//		
		if (	(dragging)	) {
			boolean placeFound = false;
			for (IHolder ih: holders) {
				if (ih.contains(e.getPoint())) {
					//System.out.println("in mouseRel");
					dstHolder=ih;
					model.moveTo(ih);
					placeFound = true;
				}										
			}
			
			if (!placeFound) {	
				dstHolder=srcHolder;
				model.moveTo(srcHolder);		
			}
			
			//
			//System.out.println("here too");
			dragging=false;
		}
	}
	
	
	public void update(Observable o) {		
			srcHolder.renderContent();
			dstHolder.renderContent();
	}
}
